﻿using GISServer.Core.Client.Geometry;

namespace GeometryServer.Extensions
{
    public static class ComputeProject
    {
        public static void Project(this Point point, int insrid, int outsrid)
        {
            var xy = new double[2];
            xy[0] = point.X;
            xy[1] = point.Y;
            var projectedpoint = DotSpatialProjectPoint(xy, insrid, outsrid);
            point.X = projectedpoint.X;
            point.Y = projectedpoint.Y;
        }

        public static void Project(this MultiPoint multipoint, int insrid, int outsrid)
        {
            for (int i = 0; i < multipoint.Points.Count; i++)
            {
                (multipoint.Points[i] as Point).Project(insrid, outsrid);
            }
        }

        public static void Project(this Polyline polyline, int insrid, int outsrid)
        {
            for (int i = 0; i < polyline.Paths.Count; i++)
            {
                for (int j = 0; j < polyline.Paths[i].Count; j++)
                {
                    (polyline.Paths[i][j] as Point).Project(insrid, outsrid);
                }
            }
        }

        public static void Project(this Polygon polygon, int insrid, int outsrid)
        {
            for (int i = 0; i < polygon.Rings.Count; i++)
            {
                for (int j = 0; j < polygon.Rings[i].Count; j++)
                {
                    (polygon.Rings[i][j] as Point).Project(insrid, outsrid);
                }
            }
        }

        public static void Project(this Envelope envelope, int insrid, int outsrid)
        {
            var minpoint = new Point(envelope.XMin, envelope.YMin);
            var maxpoint = new Point(envelope.XMax, envelope.YMax);
            minpoint.Project(insrid, outsrid);
            maxpoint.Project(insrid, outsrid);
            envelope.XMin = minpoint.X;
            envelope.YMin = minpoint.Y;
            envelope.XMax = maxpoint.X;
            envelope.YMax = maxpoint.Y;
        }

        public static void Project(this GeometryArray geometryarray, int insrid, int outsrid)
        {
            switch (geometryarray.GeometryType)
            {
                case "esriGeometryPoint":

                    for (int i = 0; i < geometryarray.Geometries.Count; i++)
                    {
                        (geometryarray.Geometries[i] as Point).Project(insrid, outsrid);
                    }

                    break;
                case "esriGeometryMultipoint":

                    for (int i = 0; i < geometryarray.Geometries.Count; i++)
                    {
                        (geometryarray.Geometries[i] as MultiPoint).Project(insrid, outsrid);
                    }
                    break;
                case "esriGeometryPolyline":

                    for (int i = 0; i < geometryarray.Geometries.Count; i++)
                    {
                        (geometryarray.Geometries[i] as Polyline).Project(insrid, outsrid);
                    }
                    break;
                case "esriGeometryPolygon":

                    for (int i = 0; i < geometryarray.Geometries.Count; i++)
                    {
                        (geometryarray.Geometries[i] as Polygon).Project(insrid, outsrid);
                    }
                    break;
                case "esriGeometryEnvelope":

                    for (int i = 0; i < geometryarray.Geometries.Count; i++)
                    {
                        (geometryarray.Geometries[i] as Envelope).Project(insrid, outsrid);
                    }
                    break;
            }
            //geometryarray.SpatialReference = new SpatialReference(outsrid);
        }


        private static Point DotSpatialProjectPoint(double[] xy, int insrid, int outsrid)
        {
            double[] z = new double[1];
            z[0] = 1;

            DotSpatial.Projections.ProjectionInfo pStart = DotSpatial.Projections.ProjectionInfo.FromEpsgCode(insrid);

            DotSpatial.Projections.ProjectionInfo pEnd = DotSpatial.Projections.ProjectionInfo.FromEpsgCode(outsrid);

            DotSpatial.Projections.Reproject.ReprojectPoints(xy, z, pStart, pEnd, 0, 1);
            return new Point(xy[0], xy[1]);
        }
    }
}